package com.bangwz.aio;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

public class AsyncClientHandler implements CompletionHandler<Void, AsyncClientHandler>, Runnable {

	private String addr;

	private int port;

	private AsynchronousSocketChannel channel;

	private CountDownLatch latch;

	public AsyncClientHandler(String addr, int port) throws IOException {
		this.addr = addr;
		this.port = port;
		// 创建channel
		channel = AsynchronousSocketChannel.open();
	}

	public AsynchronousSocketChannel getChannel() {
		return channel;
	}

	public void setChannel(AsynchronousSocketChannel channel) {
		this.channel = channel;
	}

	public CountDownLatch getLatch() {
		return latch;
	}

	public void setLatch(CountDownLatch latch) {
		this.latch = latch;
	}

	@Override
	public void run() {
		latch = new CountDownLatch(1);
		channel.connect(new InetSocketAddress(addr, port), this, this);
		try {
			// 阻塞到这里
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		try {
			channel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void completed(Void result, AsyncClientHandler handler) {
		System.out.println("客户端成功连接到服务器...");
	}

	@Override
	public void failed(Throwable exc, AsyncClientHandler handler) {
		System.err.println("连接服务器失败...");
		exc.printStackTrace();
		handler.latch.countDown();
	}
}

class ClientWriteHandler implements CompletionHandler<Integer, ByteBuffer> {

	private AsynchronousSocketChannel clientChannel;
	private CountDownLatch latch;

	public ClientWriteHandler(AsynchronousSocketChannel clientChannel, CountDownLatch latch) {
		this.clientChannel = clientChannel;
		this.latch = latch;
	}

	@Override
	public void completed(Integer result, ByteBuffer buffer) {
		if (buffer.hasRemaining()) {
			clientChannel.write(buffer, buffer, this);
		}
		// else {
		// // TODO！读取数据
		// clientChannel.read(buffer, buffer, new ClientReadHandler(clientChannel, latch));
		// }
	}

	@Override
	public void failed(Throwable exc, ByteBuffer attachment) {
		System.err.println("数据发送失败...");
		exc.printStackTrace();
		latch.countDown();
	}
}

class ClientReadHandler implements CompletionHandler<Integer, ByteBuffer> {

	private AsynchronousSocketChannel clientChannel;
	private CountDownLatch latch;

	public ClientReadHandler(AsynchronousSocketChannel clientChannel, CountDownLatch latch) {
		this.clientChannel = clientChannel;
		this.latch = latch;
	}

	@Override
	public void completed(Integer result, ByteBuffer buffer) {
		buffer.flip();
		byte[] bytes = new byte[buffer.remaining()];
		buffer.get(bytes);
		String body = null;
		try {
			body = new String(bytes, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println("客户端收到结果:" + body);
	}

	@Override
	public void failed(Throwable exc, ByteBuffer attachment) {
		System.err.println("数据接收失败...");
		exc.printStackTrace();
		latch.countDown();
	}

}
